import axios from "axios";
import type {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import { getErrorMsg } from "./code";
import type { Result } from "../request";
import { multiConfig } from "..";
import { Message } from "element-ui";
// import JSONbig from "json-bigint";
import router from "@/router";
import { casCode, errorCodeDesc, loginOutCode } from "./casCode";

export class Request {
  private instance: AxiosInstance;
  private baseConfig: AxiosRequestConfig = {
    // baseURL: import.meta.env.VITE_REQ_URL,  // 微服务端口不一样，所以无法统一制定baseURL
    timeout: 35000,
  };
  constructor(config: multiConfig) {
    // 使用axios.create创建axios实例，配置:基础配置和传递进来的配置
    this.instance = axios.create(
      Object.assign(
        this.baseConfig,
        config
        //   {
        //   // 有时候后端返回的数字太长了
        //   transformResponse: [
        //     (data: any) => {
        //       try {
        //         return JSONbig.parse(data);
        //       } catch (err) {
        //         return data;
        //       }
        //     },
        //   ],
        // }
      )
    );
    // 请求拦截器,添加cookie或者token
    this.instance.interceptors.request.use(
      // https://blog.csdn.net/huangfengnt/article/details/131490913 解释了一下1.3版本后的类型变化
      (config: InternalAxiosRequestConfig<any>) => {
        const token = localStorage.getItem("token");
        if (token) {
          config.headers!["finance-authentication"] = token;
        }
        config.withCredentials = true; // 允许携带cookie
        return config;
      },
      (err: any) => {
        return Promise.reject(err);
      }
    );
    this.instance.interceptors.response.use(
      (res: AxiosResponse) => {
        // console.log("配置", config);
        if (config.needOrigin) {
          return res;
        }
        if (res.data) {
          const code = res.data.code as casCode;
          if (errorCodeDesc[code]) {
            Message.error(errorCodeDesc[code]);
            // token失效和无用才跳转login
            if (loginOutCode.includes(code)) {
              router.push("/login").catch((err) => {
                // 只有当路由不重复时的报错才抛出
                if (err.name !== "NavigationDuplicated") {
                  throw err;
                }
              });
            }
          }
        }
        return res.data;
      },
      (err: any) => {
        getErrorMsg(err);
        // todo 加入elmessage组件
        return Promise.reject(err.response);
      }
    );
  }
  //   定义基本的请求方法
  public request(config: AxiosRequestConfig): Promise<AxiosResponse> {
    return this.instance.request(config);
  }
  /** 各类methods **/
  public get<T = any>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<Result<T>> | Promise<AxiosResponse>> {
    console.log("get参数", config);
    return this.instance.get(url, config);
  }
  //   泛型输入给自己找事，但是利于检查和提示
  public post<T = any, D = any>(
    url: string,
    data?: D,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<Result<T>>> {
    return this.instance.post(url, data, config);
  }
  public put<T = any, D = any>(
    url: string,
    data?: D,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<Result<T>>> {
    return this.instance.put(url, data, config);
  }
  public delete<T = any>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<Result<T>>> {
    return this.instance.delete(url, config);
  }
}
